package com.qzdatasoft.ratelimit.core;

import jakarta.servlet.FilterChain;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;

public class RequestTask {
    private final HttpServletRequest request;
    private final HttpServletResponse response;
    private final FilterChain chain;
    private final long enqueueTime; // 在队列中的已等待时间
    private final CompletableFuture<Boolean> future = new CompletableFuture<>();
    private final AtomicBoolean finished = new AtomicBoolean(false);

    // keys (for counters)
    private String resourceKey;
    private LeakyBucketLimiter limiter;
//    private String url;
//    private String ip;
//    private String user;

    public RequestTask(HttpServletRequest request, HttpServletResponse response, FilterChain chain) {
        this.request = request;
        this.response = response;
        this.chain = chain;
        this.enqueueTime = System.nanoTime();
    }

    public HttpServletRequest getRequest() { return request; }
    public HttpServletResponse getResponse() { return response; }
    public FilterChain getChain() { return chain; }
    public long getEnqueueTime() { return enqueueTime; }

    public void setResourceKey(String resourceKey) {
        this.resourceKey = resourceKey;
    }
    public String getResourceKey() { return resourceKey; }

    public void setLimiter(LeakyBucketLimiter limiter) {
        this.limiter = limiter;
    }
    public LeakyBucketLimiter getLimiter() {
        return limiter;
    }

//    public void setKeys(String url, String ip, String user) {
//        this.url = url;
//        this.ip = ip;
//        this.user = user;
//    }
//    public String getUrl() { return url; }
//    public String getIp() { return ip; }
//    public String getUser() { return user; }

    public boolean tryCompleteAllow() {
        if (finished.compareAndSet(false, true)) {
            return future.complete(Boolean.TRUE);
        }
        return false;
    }
    public boolean tryCompleteReject() {
        if (finished.compareAndSet(false, true)) {
            return future.complete(Boolean.FALSE);
        }
        return false;
    }

    public boolean awaitAllowed(/*long timeoutNanos*/) throws InterruptedException {
        // 如果 limiter 为空则表示不受限，直接放行
        if(null==limiter) return true;

        long timeoutNanos = limiter.getProps().getTimeoutNanos();
        try {
            Boolean b = future.get(timeoutNanos, TimeUnit.NANOSECONDS);
            return Boolean.TRUE.equals(b);
        } catch (TimeoutException ex) {
            return false;
        } catch (java.util.concurrent.ExecutionException ex) {
            return false;
        }
    }

    // equals/hashCode based on identity to allow removal from queue
    @Override
    public boolean equals(Object obj) {
        return this == obj;
    }

    @Override
    public int hashCode() {
        return System.identityHashCode(this);
    }
}